// EmployeeExcelListener.java
package com.example.springboothomework.config;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.example.springboothomework.common.ImportError;
import com.example.springboothomework.dao.CompanyDao;
import com.example.springboothomework.dao.EmployeeDao;
import com.example.springboothomework.entity.Employee;
import com.example.springboothomework.entity.excel.EmployeeExcelImport;
import com.example.springboothomework.mapper.EmployeeMapper;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author chenjianhao
 * @date 2025/6/10
 *
 * Excel导入监听器
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class EmployeeExcelListener extends AnalysisEventListener<EmployeeExcelImport> {

    // 批处理大小
    private static final int BATCH_SIZE = 1000;
    
    private final Validator validator;
    private final EmployeeDao employeeDao;
    private final EmployeeMapper employeeMapper;
    private final CompanyDao companyDao;

    // 员工list
    private final List<Employee> dataList = new ArrayList<>();

    // 错误集合
    @Getter
    private final List<ImportError> errors = new ArrayList<>();
    // 计数器
    @Getter
    private int total = 0;
    @Getter
    private int success = 0;
    @Getter
    private int fail = 0;

    /**
     * 每一条数据解析都会来调用
     * @param data
     * @param context
     */
    @Override
    public void invoke(EmployeeExcelImport data, AnalysisContext context) {
        total++;
        // 获取实际行号(从1开始)
        int rowIndex = context.readRowHolder().getRowIndex() + 1;
        
        // 数据校验
        Set<ConstraintViolation<EmployeeExcelImport>> violations = validator.validate(data);
        // 校验失败
        if (!violations.isEmpty()) {
            fail++;
            String errorMsg = violations.stream()
                    .map(ConstraintViolation::getMessage)
                    .collect(Collectors.joining(";"));
            errors.add(new ImportError(rowIndex, errorMsg,data));
            return;
        }
        try {
            // 转为实体类
            String companyName = data.getCompanyName();
            //公司是否存在
            Long companyId = companyDao.findIdByName(companyName);
            if(companyId==null){
                log.error("行[{}]数据转换失败: {}", rowIndex,"公司名称不存在");
                fail++;
                errors.add(new ImportError(rowIndex, "公司名称不存在",data));
                return;
            }
            Employee employee = employeeMapper.importToEntity(data,companyId);
            dataList.add(employee);
            
            // 达到批处理大小时保存
            if (dataList.size() >= BATCH_SIZE) {
                saveBatch();
            }
        } catch (Exception e) {
            log.error("行[{}]数据转换失败: {}", rowIndex, e.getMessage());
            fail++;
            errors.add(new ImportError(rowIndex, "数据转换失败: " + e.getMessage(),data));
        }
    }

    /**
     * 所有数据解析完成会来调用
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 处理剩余数据
        if (!dataList.isEmpty()) {
            saveBatch();
        }
        log.info("Excel解析完成: 总计={}, 成功={}, 失败={}", total, success, fail);
    }

    /**
     * 批量保存数据
     */
    private void saveBatch() {
        if (dataList.isEmpty()) return;

        try {
            // 批量保存
            List<Employee> saved = employeeDao.saveAll(dataList);
            success += saved.size();
            log.info("批量保存员工数据: {}条", saved.size());
        } catch (Exception e) {
            fail += dataList.size();
            log.error("批量保存失败: {}", e.getMessage());
            // 记录批量错误信息
            errors.add(new ImportError(
                -1, 
                "批量保存失败(行" + (total - dataList.size() + 1) +
                "到" + total + "): " + e.getMessage()
                    ));
        } finally {
            // 清空缓存
            dataList.clear();
        }
    }
}